﻿using System;

namespace Demo
{
    class Program
    {
        static void Main(string[] args)
        {

            var a1 = new A();
            var a2 = new A();
            A0 a0 = a2;
            Console.WriteLine($"Equals->{a1.Equals(a2)}");
            Console.WriteLine($"ReferenceEquals->{ReferenceEquals(a1, a2)}" );


            /****
             * Object 中的 Equals 方法调用了
             * RuntimeHelpers.Equals(this, obj); 
             * 
             *  [SecuritySafeCritical]
		        [MethodImpl(MethodImplOptions.InternalCall)]
		        public new static extern bool Equals(object o1, object o2);
             * ****/
            Console.WriteLine(a0.Equals(a2));
            Console.WriteLine(ReferenceEquals(a0,a2));

            Console.WriteLine("=================");

            var b1 = new B();
            b1.Name = "222";
            var b2 = new B();
            b2.Name = "222";

            /***
             * 因为值类型(System.ValueType)重写了Equals 方法
             * public override bool Equals(object obj)
		        {
			        if (obj == null)
			        {
				        return false;
			        }
			        RuntimeType runtimeType = (RuntimeType)base.GetType();
			        RuntimeType left = (RuntimeType)obj.GetType();
			        if (left != runtimeType)
			        {
				        return false;
			        }
			        if (ValueType.CanCompareBits(this))
			        {
				        return ValueType.FastEqualsCheck(this, obj);
			        }
			        FieldInfo[] fields = runtimeType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			        for (int i = 0; i < fields.Length; i++)
			        {
				        object obj2 = ((RtFieldInfo)fields[i]).UnsafeGetValue(this);
				        object obj3 = ((RtFieldInfo)fields[i]).UnsafeGetValue(obj);
				        if (obj2 == null)
				        {
					        if (obj3 != null)
					        {
						        return false;
					        }
				        }
				        else if (!obj2.Equals(obj3))
				        {
					        return false;
				        }
			        }
			        return true;
		        }
             * 
             * 1.b2 为null 返回false
             * 2.引用不同返回false
             * 3.利用反射对每个字段比较，有一个不同返回false，自己用 值类型 可以重新实现Equals 方法
             * 4.最后返回true， 但是ValueType 的Equals  不会调用objcet 的Equals 方法的
             * **/
            Console.WriteLine(b1.Equals(b2));
            
           

            Console.WriteLine(ReferenceEquals(b1, b2));


            Console.WriteLine("动态类型");

            dynamic value;
            for (int i = 0; i < 10; i++)
            {
                if (i == 3 || i==1 || i==5)
                {
                    value = i;
                }
                else
                {
                    value = "A" + i;
                }
                M(value);
            }




            Console.WriteLine("Hello World!");
        }

        public static void M(int n)
        {
            Console.WriteLine($"int ===>{n}");
        }
        public static void M(string n)
        {
            Console.WriteLine($"string -》{n}");
        }

    }

    public class A0 { public string Name { get; set; } }
    public class A:A0
    {
       
        public int Age { get; set; }

    }


    public struct B
    {
        public string Name { get; set; }
        public int Age { get; set; }

    }

}
